package com.koron.car.web.maintain.service.impl;


import com.alibaba.fastjson.JSON;
import com.koron.bean.base.Response;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.bean.workflow.RedirectQuery;
import com.koron.car.config.Constants;
import com.koron.car.web.applycar.service.impl.DriverRecordServiceImpl;
import com.koron.car.web.carledger.bean.vo.CarVO;
import com.koron.car.web.carledger.service.CarService;
import com.koron.car.web.common.CommonUtils;
import com.koron.car.web.costregister.bean.entity.CostRegister;
import com.koron.car.web.costregister.mapper.CostRegisterMapper;
import com.koron.car.web.costregister.service.CostRegisterService;
import com.koron.car.web.maintain.bean.entity.AcceptRecord;
import com.koron.car.web.maintain.bean.entity.CarMaintain;
import com.koron.car.web.maintain.bean.query.CarMaintainQuery;
import com.koron.car.web.maintain.bean.vo.CarMaintainVO;
import com.koron.car.web.maintain.client.SysWorkflowClient;
import com.koron.car.web.maintain.mapper.AcceptRecordMapper;
import com.koron.car.web.maintain.mapper.CarMaintainMapper;
import com.koron.car.web.maintain.service.AcceptRecordService;
import com.koron.car.web.maintain.service.CarMaintainService;
import com.koron.car.web.motorcade.service.PrimaryOrgService;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.OrgCacheUtils;
import com.koron.common.core.util.SpringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * (CarMaintain)表服务实现类
 * @author twcao
 * @since 2022-03-13 14:28:13
 */
@Service
public class CarMaintainServiceImpl implements CarMaintainService {

    @Autowired
    private AcceptRecordService acceptService;

    @Autowired
    private CarService carService;

    @Autowired
    private OrgCacheUtils orgCacheUtils;

    @Autowired
    private PrimaryOrgService primaryOrgService;

    @Autowired
    private SysWorkflowClient sysWorkflowClient;

    @Autowired
    private CostRegisterService costRegisterService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    @TaskAnnotation("queryById")
    public CarMaintainVO queryById(SessionFactory factory, String id) {
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        CarMaintainVO maintain = mapper.queryById(id);
        List<String> primary = primaryOrgService.isPrimary(factory, Arrays.asList(maintain.getOwnerOrg()));
        maintain.setPrimary(primary.contains(maintain.getOwnerOrg()) ? Constants.Primary.YES : Constants.Primary.NO);
        maintain.setOwnerOrgName(orgCacheUtils.getOrgNameById(maintain.getOwnerOrg()));
        List<AcceptRecord> accepts = maintain.getAccepts();
        if(CollectionUtils.isNotEmpty(accepts)) {
            Optional<AcceptRecord> optional = accepts.stream().filter(row -> Objects.isNull(row.getFinishTime())).findFirst();
            maintain.setAccept(optional.orElse(null));
        }

        return maintain;
    }

    /**
     * 查询多条数据
     * @param query 查询条件
     * @return 对象列表
     */
    @Override
    @TaskAnnotation("queryList")
    public List<CarMaintainVO> queryList(SessionFactory factory, CarMaintainQuery query) {
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        List<CarMaintainVO> maintains = mapper.queryList(query);
        maintains.stream().forEach(row -> row.setOwnerOrgName(orgCacheUtils.getOrgNameById(row.getOwnerOrg())));
        return maintains;
    }

    /**
     * 新增数据
     * @param maintain 实例对象
     * @return 实例对象
     */
    @Override
    @TaskAnnotation("insert")
    public CarMaintainVO insert(SessionFactory factory, CarMaintainVO maintain) {
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        Assert.notNull(maintain, "实体不能为空");
        maintain.setMaintainType(Constants.MaintainType.REPAIR);
        Assert.hasText(maintain.getMaintainType(), "维修保养类型不能为空");
        EamUser eamUser = ThreadLocalContext.get();
        CommonUtils.update(maintain, eamUser);
        maintain.setDeptId(eamUser.getOrgId());
        maintain.setId(CodeTools.getCode32());
        Assert.isTrue(maintain.getAppointPlace() != null, "请选择是否定点维修/保养");
        Assert.isTrue(maintain.getAppraise() != null, "请输入维修估价");
        if(StringUtils.equals(maintain.getMaintainType(), Constants.MaintainType.REPAIR)) {
            // 维修
            maintain.setCode(CommonUtils.getCodeNo(Constants.CAR_MAINTAIN_CODE, 3));
        } else {
            // 保养
            maintain.setCode(CommonUtils.getCodeNo(Constants.CAR_KEEPUP_CODE, 3));
        }
        maintain.setState(Constants.MaintainState.DRAFT);
        mapper.insert(maintain);
        return queryById(factory, maintain.getId());
    }

    /**
     * 修改数据
     * @param maintain 实例对象
     * @return 实例对象
     */
    @Override
    @TaskAnnotation("update")
    public CarMaintainVO update(SessionFactory factory, CarMaintainVO maintain) {
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        CommonUtils.update(maintain, ThreadLocalContext.get());
        if(StringUtils.isBlank(maintain.getCode())) {
            String code = CommonUtils.getCodeNo(StringUtils.equals(maintain.getMaintainType(), Constants.MaintainType.REPAIR) ? Constants.CAR_MAINTAIN_CODE : Constants.CAR_KEEPUP_CODE, 3);
            maintain.setCode(code);
        }
        Assert.isTrue(maintain.getAppointPlace() != null, "请选择是否定点维修/保养");
        Assert.isTrue(maintain.getAppraise() != null, "请输入维修估价");
        AcceptRecord accept = maintain.getAccept();
        if(!Objects.isNull(accept)) {
            accept.setApplyId(maintain.getId());
            // 保存/更新验收信息
            acceptService.saveOrUpdate(factory, accept);
        }
        // 更新维修保养单
        mapper.update(maintain);
        return queryById(factory, maintain.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    @TaskAnnotation("deleteById")
    public boolean deleteById(SessionFactory factory, String id) {
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        return mapper.deleteById(id) > 0;
    }

    /**
     * 提交
     *
     * @param factory
     * @param id
     * @return
     */
    @Override
    @TaskAnnotation("submit")
    public CarMaintainVO submit(SessionFactory factory, String id) {
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        CostRegisterMapper costRegisterMapper = factory.getMapper(CostRegisterMapper.class);
        CarMaintainVO maintain = mapper.queryById(id);
        Assert.notNull(maintain, "维修保养记录不存在");
        // 提交前的状态
        String state = maintain.getState();
        int index = Constants.MaintainState.stateList.indexOf(state);
        Assert.isTrue(index < Constants.MaintainState.stateList.size() - 1, "流程已完成");
        // 提交后的状态
        String newState = Constants.MaintainState.stateList.get(index + 1);
        CarMaintainVO carMaintain = new CarMaintainVO();
        // 默认提交成功后修改状态
        carMaintain.setState(newState);
        switch (newState) {
            case Constants.MaintainState.WAIT_ARRANGE:
                // 修改车辆的状态为检修
                String carId = maintain.getCarId();
                Assert.hasText(carId, "车辆id不能为空");
                carService.updateState(factory, carId, Constants.CarState.MAINTENANCE);
                break;
            case Constants.MaintainState.FINISH:
                AcceptRecordMapper acceptMapper = factory.getMapper(AcceptRecordMapper.class);
                // 如果提交后是验收，则检查是否验收通过
                List<AcceptRecord> accepts = maintain.getAccepts();
                Assert.notEmpty(accepts, "请先完成验收");
                AcceptRecord accept = accepts.stream().filter(row -> Objects.isNull(row.getFinishTime())).findFirst().get();
                Assert.notNull(accept, "请先保存验收信息");
                if(Constants.YesOrNo.NO.equals(accept.getQualified())) {
                    // 如果没有验收成功
                    carMaintain.setState(Constants.MaintainState.FINISH);
                } else {
                    // 如果合格了，设置repair_end_time, 并将车辆设置为空闲
                    carMaintain.setRepairEndTime(new Date());
                    carService.updateState(factory, maintain.getCarId(), Constants.CarState.FREE);
                }
                // 只在提交验收时，才设置验收的完成时间
                accept.setFinishTime(new Date());
                acceptMapper.saveOrUpdate(accept);
                CarVO carVO = carService.queryById(factory, maintain.getCarId());
                // 更新费用
                CostRegister matainCostRegister = new CostRegister();
                matainCostRegister.setId(CodeTools.getCode32());
                matainCostRegister.setDriverId(maintain.getApplicantId());
                matainCostRegister.setCostType(Constants.FeeType.MATAINFEE);
                matainCostRegister.setCost(maintain.getActualPrice());
                matainCostRegister.setState(Constants.FeeState.FINISH);
                matainCostRegister.setLicPlateNum(maintain.getLicPlateNum());
                matainCostRegister.setDriverName(maintain.getApplicantName());
                matainCostRegister.setMaintainCode(maintain.getCode());
                matainCostRegister.setStartTime(new Date());
                matainCostRegister.setPlace(maintain.getRepairPlace());
                matainCostRegister.setRemark(maintain.getRemark());
                matainCostRegister.setMotorcade(carVO.getMotorcade());
                matainCostRegister.setCarId(carVO.getId());
                DriverRecordServiceImpl driverRecordService = SpringUtils.getBean(DriverRecordServiceImpl.class);
                driverRecordService.setCostProperty(matainCostRegister);
                costRegisterMapper.insert(matainCostRegister);
                break;
            default:
                break;
        }
        // 如果验收成功，更新维修保养状态
        carMaintain.setId(maintain.getId());
        maintain.setState(carMaintain.getState());
        CommonUtils.update(carMaintain, ThreadLocalContext.get());
        mapper.update(carMaintain);

        return maintain;
    }

    /**
     * 工作流更新
     *
     * @param factory
     * @param redirectQuery
     */
    @Override
    @TaskAnnotation("workflowUpdate")
    public Boolean workflowUpdate(SessionFactory factory, RedirectQuery redirectQuery) {
        Integer operation = redirectQuery.getOperation();
        CarMaintainVO vo = JSON.parseObject(redirectQuery.getFormVariables(), CarMaintainVO.class);
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        switch (operation) {
            case 1: // 驳回
                // 驳回的节点编号
                vo.setState(Constants.MaintainState.DRAFT);
                break;
            case 32: // 同意
                vo.setState(Constants.MaintainState.WAIT_REVIEW);
                break;
            default:
                break;
        }
        // 更新状态
        CarMaintain maintain = new CarMaintain();
        maintain.setId(vo.getId());
        maintain.setState(vo.getState());
        mapper.update(maintain);
        return true;
    }

    /**
     * 审核完成(状态改为待派车)
     *
     * @param factory
     * @param detail
     * @return
     */
    @Override
    @TaskAnnotation("auditFinish")
    public CarMaintainVO auditFinish(SessionFactory factory, CarMaintainVO detail) {
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        detail.setState(Constants.MaintainState.WAIT_ARRANGE);
        CarMaintain maintain = new CarMaintain();
        maintain.setId(detail.getId());
        maintain.setState(detail.getState());
        mapper.update(maintain);
        return detail;
    }

    @Override
    @TaskAnnotation("queryRepairPlace")
    public List<String> queryRepairPlace(SessionFactory factory) {
        CarMaintainMapper mapper = factory.getMapper(CarMaintainMapper.class);
        return mapper.queryRepairPlace();
    }

    @Override
    @TaskAnnotation("getPrintData")
    public Map<String, Object> getPrintData(SessionFactory factory, String findId, String id) {
        CarMaintainServiceImpl maintainService = SpringUtils.getBean(this.getClass());
        CarMaintainVO carMaintainVO = maintainService.queryById(factory, id);
        Assert.notNull(carMaintainVO,"当前维修申请单不存在！");
        Response<Object> response = sysWorkflowClient.workflowMobileHistory(findId);
        Map<String,Object> data = (Map<String, Object>) response.getData();
        Assert.notNull(data,"当前维修申请流程不存在！");
        Map<String,Object> result = new HashMap<>();
        Map<Object,Object> history = new HashMap<>();
        result.put("carMaintainVO",carMaintainVO);
        List<Map<String,Object>> historyList = (List<Map<String,Object>>) data.get("history");
        Map<Object, List<Map<String, Object>>> mapByNode = historyList.stream().collect(Collectors.groupingBy(map -> map.get("nowNodeId")));
        Set<Map.Entry<Object, List<Map<String, Object>>>> entries = mapByNode.entrySet();
        entries.forEach(e->{
            Map<String, Object> map = e.getValue().get(e.getValue().size() - 1);
            history.put(e.getKey(),map);
        });
        result.put("workflow",history);
        return result;
    }
}
